/*
 * @(#)Class.java        0.1 09/04/29
 * @version 	0.1 29 Apr 2009
 * @author 	Tran Dai Hiep, Nguyen Thang Huy
 * 
 * Luu tru du lieu cua mot Class (hoac Enum, Interface), doc du lieu tu XML
 */


package Data;

import GUI.*;
import XML_IO.*;

import java.util.*;
import javax.swing.*;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class Class {
	public static final int CLASS = 0;
	public static final int ABSTRACT_CLASS = 1;
	public static final int ENUM = 2;
	public static final int INTERFACE = 3;
	static long numberOfClass = 0;
	long id;
	int type;
	String name;
	LinkedList<Class> bases;
	LinkedList<String> attributes;
	LinkedList<String> methods;
	
	public Class() {
		id = numberOfClass;
		type = 0;
		numberOfClass++;
		name = "";
		bases = new LinkedList<Class>();
		attributes = new LinkedList<String>();
		methods = new LinkedList<String>();
	}
	
	public Class(int t) {
		this();
		type = t;
	}
	
	public Class(Class c) {
		this();
		if (c != null) {
			name = c.name;
			bases = new LinkedList<Class>(c.bases);
			attributes = new LinkedList<String>(c.attributes);
			methods = new LinkedList<String>(c.methods);
		}
	}
	
	/*
	 * Doc du lieu 1 class tu XML
	 */
	public Class (Node node) {
		this();
		NamedNodeMap atts = node.getAttributes();
		for (int k=0; k<atts.getLength(); k++)
    	{
    		Node att = atts.item(k);
    		if (att.getNodeName().equals("type")) {
    			type = Integer.parseInt(XML_IO.getElementValue(att));
    		}
    	}
		
		NodeList children = node.getChildNodes();
		for (int i = 0; i < children.getLength(); i++) {
			Node child = children.item(i);
			if (child.getNodeType() == Node.ELEMENT_NODE) {
				//Doc ten
				if (child.getNodeName().equals("name")) {
					name = XML_IO.getElementValue(child);
				}
				//Doc id
				if (child.getNodeName().equals("id")) {
					id = Integer.parseInt(XML_IO.getElementValue(child));
					if (id >= numberOfClass) {
						numberOfClass = id + 1;
					}
				}
				//Doc cac Attribute
				if (child.getNodeName().equals("attributes")) {
					NodeList tmp = child.getChildNodes();
					for (int j = 0; j < tmp.getLength(); j++) {
						if (tmp.item(j).getNodeType() == Node.ELEMENT_NODE && tmp.item(j).getNodeName().equals("attribute")) {
							attributes.add(XML_IO.getElementValue(tmp.item(j)));
						}
					}
				}
				//Doc cac Method
				if (child.getNodeName().equals("methods")) {
					NodeList tmp = child.getChildNodes();
					for (int j = 0; j < tmp.getLength(); j++) {
						if (tmp.item(j).getNodeType() == Node.ELEMENT_NODE && tmp.item(j).getNodeName().equals("method")) {
							methods.add(XML_IO.getElementValue(tmp.item(j)));
						}
					}
				}
			}
		}
	}
	
	public Class copy(Class c) {
		Class tmp = new Class(c);
		tmp.id = c.id;
		return tmp;
	}
	
	public long getId() {
		return id;
	}
	
	public int getType() {
		return type;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String n) {
		name = n;
	}
	
	/*
	 * Them mot lop co so
	 */
	public boolean addBase(Class b) {
		if (bases.indexOf(b) == -1) {
			bases.addLast(b);
			return true;
		} else return false;
	}
	
	/*
	 * Them attribute
	 */
	public void addAttribute(String a) {
			attributes.addLast(a);
	}
	
	/*
	 * Them Method
	 */
	public void addMethod(String m) {
		if (canUpdateMethod(m)) {
			methods.addLast(m);
		}
	}
	
	/*
	 * Xoa lop co so
	 */
	public void removeBase(Class b) {
		bases.remove(b);
	}
	
	/*
	 * Xoa attribute
	 */
	public void removeAttribute(String a) {
		attributes.remove(a);
	}
	
	/*
	 * Xoa method
	 */
	public void removeMethod(String m) {
		methods.remove(m);
	}
	
	/*
	 * Xoa tat ca cac lop co so
	 */
	public void removeBases() {
		bases = new LinkedList<Class>();
	}
	
	/*
	 * Xoa tat ca cac attribute
	 */
	public void removeAttributes() {
		attributes = new LinkedList<String>();
	}
	
	/*
	 * Xoa tat ca cac method
	 */
	public void removeMethods() {
		methods = new LinkedList<String>();
	}
	
	public LinkedList<Class> getBases() {
		return new LinkedList<Class>(bases);
	}
	
	public LinkedList<String> getAttributes() {
		return attributes;
	}
	
	public LinkedList<String> getMethods() {
		return methods;
	}
	
	public boolean canUpdateMethod(String m) {
		if (methods.indexOf(m) == -1) return true;
		else return false;
	}
	
	/*
	 * Chuyen thong tin class thanh XML de luu tru
	 */
	public Node toXml(Document doc) {
    	Element classElement = doc.createElement("class");
    	classElement.setAttribute("x", getClassFrame().getX() + "");
    	classElement.setAttribute("y", getClassFrame().getY() + "");
    	classElement.setAttribute("height", getClassFrame().getHeight() + "");
    	classElement.setAttribute("width", getClassFrame().getWidth() + "");
    	classElement.setAttribute("type", type + "");
    	// Chuyen ten
    	Element nameElement = doc.createElement("name");
    	nameElement.appendChild(doc.createTextNode(name));
    	classElement.appendChild(nameElement);
    	//Chuyen id
    	Element idElement = doc.createElement("id");
    	idElement.appendChild(doc.createTextNode(id + ""));
    	classElement.appendChild(idElement);
    	
    	
    	/*Element basesElement = doc.createElement("bases");
    	classElement.appendChild(basesElement);
    	for (int i = 0; i < bases.size(); i++) {
    		Element base = doc.createElement("base");
    		base.appendChild(doc.createTextNode(bases.get(i)));
    		basesElement.appendChild(base);
    	}*/
    	
    	//Chuyen cac arttribute
    	Element attributesElement = doc.createElement("attributes");
    	classElement.appendChild(attributesElement);
    	for (int i = 0; i < attributes.size(); i++) {
    		Element attribute = doc.createElement("attribute");
    		attribute.appendChild(doc.createTextNode(attributes.get(i)));
    		attributesElement.appendChild(attribute);
    	}
    	
    	//Chuyen cac method
    	Element methodsElement = doc.createElement("methods");
    	classElement.appendChild(methodsElement);
    	for (int i = 0; i < methods.size(); i++) {
    		Element method = doc.createElement("method");
    		method.appendChild(doc.createTextNode(methods.get(i)));
    		methodsElement.appendChild(method);
    	}
    	return classElement;
	}
	
	/*
	 * Tim ClassFrame co thong tin la class nay
	 */
	public GUI.ClassFrame getClassFrame() {
		JInternalFrame frames[] = GUI.MainFrame.getAllFrames();
		for (int i = 0; i < frames.length; i++) {
			if (((ClassFrame)frames[i]).getId() == id) {
				return (ClassFrame)frames[i];
			}
		}
		return null;
	}
	
	public static void reset() {
		numberOfClass = 0;
	}
}
